JavaJNI的支持

1
2
3
4
5
6
7
8
9
10
11
12
/**
* StringAppendOperator is a merge operator that concatenates
* two strings.
*/
public class StringAppendOperator extends MergeOperator {
public StringAppendOperator() {
super(newSharedStringAppendOperator());
}

private native static long newSharedStringAppendOperator();
@Override protected final native void disposeInternal(final long handle);
}

以上代码是调用native方法的java代码.

在Java中native是关键字,它一般在本地声明,异地用C和C++来实现.

1
2
3
4
5
声明有以下几点注意:
1. native与访问控制符前后的关系不受限制.
2. 必须在返回类型之前
3. 它一般为非抽象类方法.
4. native方法在异地实现,像抽象方法一样,所以没有方法体,以分号结束.

下面是对应的C++实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
* Class: org_rocksdb_StringAppendOperator
* Method: newSharedStringAppendOperator
* Signature: (C)J
*/
jlong Java_org_rocksdb_StringAppendOperator_newSharedStringAppendOperator(
JNIEnv* /*env*/, jclass /*jclazz*/, jchar jdelim) {
auto* sptr_string_append_op =
new std::shared_ptr<ROCKSDB_NAMESPACE::MergeOperator>(
ROCKSDB_NAMESPACE::MergeOperators::CreateStringAppendOperator(
(char)jdelim));
return reinterpret_cast<jlong>(sptr_string_append_op);
}

/*
* Class: org_rocksdb_StringAppendOperator
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_StringAppendOperator_disposeInternal(JNIEnv* /*env*/,
jobject /*jobj*/,
jlong jhandle) {
auto* sptr_string_append_op =
reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::MergeOperator>*>(
jhandle);
delete sptr_string_append_op; // delete std::shared_ptr
}

问题:那这个对应关系是怎么找到的呢,就是说java的接口,怎么找到c++里的这个方法的呢?

    1. include 引入

    1. Signature: (Ljava/lang/String;)V 函数的标记符。当从本地方法端访问Java端的方法时,会用到这个标记符。JNI中为每种数据类型也定义了标记符,标记符的规则请查看JNI标准文档。

native方法的使用方式

1
2
3
1. 用loadLibrary导入存在源文件目录下的*.dll文件,
2. 然后定义native方法时,与c/c++实现的函数有相同的参数和返回类型.
3.方法被映射为固定的形式。其中函数名的映射规则是(Java_包名_类名_方法名)。

如下rocksDB中的使用方式. 见 org.rocksdb.NativeLibraryLoader

1
2
3
4
5
6
7
8
9
10
11
public synchronized void loadLibrary(final String tmpDir) throws IOException {
try {
System.loadLibrary(sharedLibraryName);
} catch(final UnsatisfiedLinkError ule1) {
try {
System.loadLibrary(jniLibraryName);
} catch(final UnsatisfiedLinkError ule2) {
loadLibraryFromJar(tmpDir);
}
}
}

.ddl ,.so文件又是什么,怎么来的呢?先说所JNI

JNI

JNI是Java Native Interface的缩写,中文为JAVA本地调用.它允许Java代码和其它语言写的代码进行交互.

JNI使得运行在JVM虚拟机上的JAVA代码能够操作使用其它语言编写的应用程序和库,比如C/C++以及汇编语言等.

JNI的设计目的:

1
2
3
 ·标准的java类库可能不支持你的程序所需的特性。
 ·或许你已经有了一个用其他语言写成的库或程序,而你希望在java程序中使用它。
 ·你可能需要用底层语言实现一个小型的时间敏感代码,比如汇编,然后在你的java程序中调用这些功能。

JAVA中native方法调用